/****************************************************************************
 * Copyright (c) 2016 - 2023 liangxiegame UNDER MIT License
 * 
 * https://qframework.cn
 * https://github.com/liangxiegame/QFramework
 * https://gitee.com/liangxiegame/QFramework
 ****************************************************************************/

using UnityEngine;
using QFramework;

namespace QFramework.Example
{
    /// <summary>
    /// 玩家状态机完整示例
    /// 演示如何使用增强的状态机系统
    /// </summary>
    public class PlayerStateMachineExample : MonoBehaviour
    {
        [Header("状态机配置")]
        public StateMachineConfig Config;
        
        [Header("玩家属性")]
        public bool IsInAir = false;
        public bool IsDashOnCooldown = false;
        public int DashCount = 0;
        public int DashLimit = 3;
        public bool IsHit = false;
        public int Health = 100;
        public float JumpHeight = 5f;
        public float MoveSpeed = 5f;
        
        // 私有变量
        private EnhancedFSM<PlayerState> fsm;
        private Rigidbody2D rb;
        private Animator animator;
        
        // 状态枚举
        public enum PlayerState
        {
            Idle,
            Run,
            Jump,
            Attack,
            Hurt,
            Dead
        }
        
        void Start()
        {
            // 获取组件
            rb = GetComponent<Rigidbody2D>();
            animator = GetComponent<Animator>();
            
            // 创建状态机
            fsm = new EnhancedFSM<PlayerState>(this);
            
            // 注册条件
            RegisterConditions();
            
            // 从配置表加载
            if (Config != null)
            {
                fsm.LoadFromConfig(Config, stateName => 
                {
                    return (PlayerState)System.Enum.Parse(typeof(PlayerState), stateName);
                });
            }
            
            // 设置状态
            SetupStates();
            
            // 开始状态
            fsm.StartState(PlayerState.Idle);
            
            // 监听状态变化
            fsm.OnStateChanged((previousState, nextState) =>
            {
                Debug.Log($"状态切换: {previousState} -> {nextState}");
            });
        }
        
        void RegisterConditions()
        {
            // 基础条件
            ConditionRegistry.Register("IsInAir", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsInAir));
            ConditionRegistry.Register("IsGrounded", new SimpleCondition(ctx => !((PlayerStateMachineExample)ctx).IsInAir));
            ConditionRegistry.Register("IsDashKeyPressed", new SimpleCondition(ctx => Input.GetKeyDown(KeyCode.LeftShift)));
            ConditionRegistry.Register("IsDashOnCooldown", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsDashOnCooldown));
            ConditionRegistry.Register("IsDashLimitReached", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).DashCount >= ((PlayerStateMachineExample)ctx).DashLimit));
            ConditionRegistry.Register("IsHit", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsHit));
            ConditionRegistry.Register("IsDead", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).Health <= 0));
            ConditionRegistry.Register("IsRunKeyPressed", new SimpleCondition(ctx => Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.A)));
            ConditionRegistry.Register("IsAttackKeyPressed", new SimpleCondition(ctx => Input.GetKeyDown(KeyCode.J)));
            ConditionRegistry.Register("IsJumpKeyPressed", new SimpleCondition(ctx => Input.GetKeyDown(KeyCode.Space)));
            
            // 复杂条件组合
            // 在空中可以冲刺的条件：在空中 && 按下冲刺键 && 没冷却 && 没到上限
            ConditionRegistry.Register("CanDashInAir", new AndCondition(
                new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsInAir),
                new SimpleCondition(ctx => Input.GetKeyDown(KeyCode.LeftShift)),
                new NotCondition(new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsDashOnCooldown)),
                new NotCondition(new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).DashCount >= ((PlayerStateMachineExample)ctx).DashLimit))
            ));
            
            // 在地面可以冲刺的条件：在地面 && 按下冲刺键 && 没冷却 && 没到上限
            ConditionRegistry.Register("CanDashOnGround", new AndCondition(
                new SimpleCondition(ctx => !((PlayerStateMachineExample)ctx).IsInAir),
                new SimpleCondition(ctx => Input.GetKeyDown(KeyCode.LeftShift)),
                new NotCondition(new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsDashOnCooldown)),
                new NotCondition(new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).DashCount >= ((PlayerStateMachineExample)ctx).DashLimit))
            ));
            
            // 受击时恢复冲刺的条件：在空中 && 受击 && 达到冲刺上限
            ConditionRegistry.Register("RecoverDashOnHitInAir", new AndCondition(
                new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsInAir),
                new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsHit),
                new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).DashCount == ((PlayerStateMachineExample)ctx).DashLimit)
            ));
            
            // 跳跃结束条件：落地
            ConditionRegistry.Register("JumpEnd", new SimpleCondition(ctx => !((PlayerStateMachineExample)ctx).IsInAir));
            
            // 攻击结束条件：攻击动画播放完毕（这里用时间模拟）
            ConditionRegistry.Register("AttackEnd", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).fsm.SecondsOfCurrentState > 0.5f));
            
            // 受击结束条件：受击动画播放完毕
            ConditionRegistry.Register("HurtEnd", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).fsm.SecondsOfCurrentState > 0.3f));
        }
        
        void SetupStates()
        {
            // Idle 状态
            fsm.State(PlayerState.Idle)
                .OnEnter(() => 
                {
                    Debug.Log("进入Idle");
                    if (animator) animator.SetTrigger("Idle");
                })
                .OnUpdate(() => 
                {
                    // 可以在这里处理输入，但主要依赖配置表驱动
                })
                .OnExit(() => Debug.Log("离开Idle"));
            
            // Run 状态
            fsm.State(PlayerState.Run)
                .OnEnter(() => 
                {
                    Debug.Log("进入Run");
                    if (animator) animator.SetTrigger("Run");
                })
                .OnUpdate(() => 
                {
                    // 处理移动
                    float horizontalInput = Input.GetAxis("Horizontal");
                    if (rb)
                    {
                        rb.velocity = new Vector2(horizontalInput * MoveSpeed, rb.velocity.y);
                    }
                })
                .OnExit(() => Debug.Log("离开Run"));
            
            // Jump 状态
            fsm.State(PlayerState.Jump)
                .OnEnter(() => 
                {
                    Debug.Log("进入Jump");
                    if (animator) animator.SetTrigger("Jump");
                    
                    // 执行跳跃
                    if (rb)
                    {
                        rb.velocity = new Vector2(rb.velocity.x, JumpHeight);
                    }
                    IsInAir = true;
                })
                .OnUpdate(() => 
                {
                    // 空中移动
                    float horizontalInput = Input.GetAxis("Horizontal");
                    if (rb)
                    {
                        rb.velocity = new Vector2(horizontalInput * MoveSpeed, rb.velocity.y);
                    }
                })
                .OnExit(() => 
                {
                    Debug.Log("离开Jump");
                    IsInAir = false;
                });
            
            // Attack 状态
            fsm.State(PlayerState.Attack)
                .OnEnter(() => 
                {
                    Debug.Log("进入Attack");
                    if (animator) animator.SetTrigger("Attack");
                })
                .OnUpdate(() => { })
                .OnExit(() => Debug.Log("离开Attack"));
            
            // Hurt 状态（可被打断）
            fsm.State(PlayerState.Hurt)
                .OnEnter(() => 
                {
                    Debug.Log("进入Hurt");
                    if (animator) animator.SetTrigger("Hurt");
                    IsHit = false; // 重置受击标志
                })
                .OnUpdate(() => { })
                .OnExit(() => Debug.Log("离开Hurt"));
            
            // Dead 状态（不可被打断）
            fsm.State(PlayerState.Dead)
                .OnEnter(() => 
                {
                    Debug.Log("进入Dead");
                    if (animator) animator.SetTrigger("Dead");
                    
                    // 禁用玩家控制
                    enabled = false;
                })
                .OnUpdate(() => { })
                .OnExit(() => Debug.Log("离开Dead"));
        }
        
        void Update()
        {
            // 更新状态机
            fsm.Update();
            
            // 测试输入
            if (Input.GetKeyDown(KeyCode.H))
            {
                IsHit = true;
                Debug.Log("玩家受击");
            }
            
            if (Input.GetKeyDown(KeyCode.K))
            {
                Health = 0;
                Debug.Log("玩家死亡");
            }
            
            // 测试冲刺
            if (Input.GetKeyDown(KeyCode.LeftShift))
            {
                if (!IsDashOnCooldown && DashCount < DashLimit)
                {
                    DashCount++;
                    Debug.Log($"使用冲刺，剩余次数: {DashLimit - DashCount}");
                    
                    // 开始冷却
                    IsDashOnCooldown = true;
                    Invoke(nameof(ResetDashCooldown), 1f);
                }
            }
        }
        
        void FixedUpdate()
        {
            fsm.FixedUpdate();
        }
        
        void OnGUI()
        {
            fsm.OnGUI();
            
            // 显示UI信息
            GUILayout.BeginArea(new Rect(10, 10, 300, 200));
            GUILayout.Label($"当前状态: {fsm.CurrentStateId}");
            GUILayout.Label($"生命值: {Health}");
            GUILayout.Label($"冲刺次数: {DashCount}/{DashLimit}");
            GUILayout.Label($"是否在空中: {IsInAir}");
            GUILayout.Label($"冲刺冷却: {IsDashOnCooldown}");
            GUILayout.Label($"受击状态: {IsHit}");
            GUILayout.Space(10);
            GUILayout.Label("控制说明:");
            GUILayout.Label("WASD - 移动");
            GUILayout.Label("空格 - 跳跃");
            GUILayout.Label("J - 攻击");
            GUILayout.Label("左Shift - 冲刺");
            GUILayout.Label("H - 受击测试");
            GUILayout.Label("K - 死亡测试");
            GUILayout.EndArea();
        }
        
        void ResetDashCooldown()
        {
            IsDashOnCooldown = false;
            Debug.Log("冲刺冷却结束");
        }
        
        void OnDestroy()
        {
            fsm?.Clear();
            ConditionRegistry.Clear();
        }
        
        // 碰撞检测（用于检测是否在地面）
        void OnCollisionEnter2D(Collision2D collision)
        {
            if (collision.gameObject.CompareTag("Ground"))
            {
                IsInAir = false;
            }
        }
        
        void OnCollisionExit2D(Collision2D collision)
        {
            if (collision.gameObject.CompareTag("Ground"))
            {
                IsInAir = true;
            }
        }
    }
} 